package com.yixin.hospital.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yixin.hospital.common.ApiResult;
import com.yixin.hospital.common.BusinessException;
import com.yixin.hospital.common.Constant;
import com.yixin.hospital.entity.bo.LimitCardInfoBo;
import com.yixin.hospital.entity.domain.PatientCard;
import com.yixin.hospital.entity.dto.req.usercard.PatientCardAddReqDTO;
import com.yixin.hospital.entity.vo.PatientCardVo;
import com.yixin.hospital.enums.CardTypeEnum;
import com.yixin.hospital.enums.PatientCardStatusEnum;
import com.yixin.hospital.enums.ResponseCodeEnum;
import com.yixin.hospital.service.PatientCardService;
import com.yixin.hospital.utils.DateUtil;
import com.yixin.hospital.utils.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/patient-card")
@Api(value = "缴费", tags = "缴费")
@Slf4j
public class PatientCardController {

    @Autowired
    private PatientCardService patientCardService;

    @GetMapping("/list")
    @ApiOperation(value = "会员卡列表")
    public ApiResult<List<PatientCardVo>> list(@RequestParam Long patientId) {
        List<PatientCard> list = patientCardService.list(new LambdaQueryWrapper<PatientCard>().eq(PatientCard::getPatientId, patientId).orderByDesc(PatientCard::getCreatedTime));
        List<PatientCardVo> response = new ArrayList();
        for (PatientCard patientCard : list) {
            PatientCardVo patientCardVo = new PatientCardVo();
            BeanUtils.copyProperties(patientCard, patientCardVo);
            patientCardVo.setStatusStr(PatientCardStatusEnum.getDesc(patientCard.getStatus()));
            if (patientCard.getCardType().equals(CardTypeEnum.LIMIT_DATE_CARD.getCode())) {
                patientCardVo.setEndTime(patientCard.getLimitCardStartDate().plusDays(patientCard.getLimitCardDays()));
            }
            response.add(patientCardVo);
        }
        return ApiResult.success(response);
    }


    @PostMapping("/add")
    @ApiOperation(value = "办卡")
    @Transactional(rollbackFor = BusinessException.class)
    public ApiResult add(@Valid @RequestBody PatientCardAddReqDTO userCardAddReqDto, HttpServletRequest request) {
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        List<PatientCardAddReqDTO.PatientCardReqDto> userCardList = userCardAddReqDto.getUserCardList();
        // 期限卡每个会员只能办一次
        this.checkLimitCard(userCardAddReqDto);
        // 储值卡只有一张，办理的储值卡 * 数量 充值到存在的储值卡余额中
        patientCardService.remove(new LambdaQueryWrapper<PatientCard>().eq(PatientCard::getPatientId, userCardAddReqDto.getPatientId()).eq(PatientCard::getStatus, PatientCardStatusEnum.PENDING.getCode()));
        for (PatientCardAddReqDTO.PatientCardReqDto patientCardReqDto : userCardList) {
            PatientCard dbPatientCard = new PatientCard();
            BeanUtils.copyProperties(patientCardReqDto, dbPatientCard);
            dbPatientCard.setPatientId(userCardAddReqDto.getPatientId());
            dbPatientCard.setStatus(PatientCardStatusEnum.PENDING.getCode());
            dbPatientCard.setCreatedBy(userName);
            dbPatientCard.setBalance(BigDecimal.ZERO);
            JSONObject parse = JSONObject.parseObject(patientCardReqDto.getCardRule().toString());
            log.info("rule: {}", parse);
            // 储值卡改变余额,PENDING状态
            if (CardTypeEnum.STORED_CARD.getCode().equals(patientCardReqDto.getCardType())) {
                BigDecimal amount = new BigDecimal(String.valueOf(parse.get("amount"))).add(new BigDecimal(String.valueOf(parse.get("giveaway"))));
                BigDecimal addBalanceAmount = amount.multiply(new BigDecimal(patientCardReqDto.getRealQuantity()));
                dbPatientCard.setBalance(addBalanceAmount);
            } else if(CardTypeEnum.LIMIT_DATE_CARD.getCode().equals(patientCardReqDto.getCardType())) {
                dbPatientCard.setLimitCardStartDate(patientCardReqDto.getStartDate().plusDays(1));
                dbPatientCard.setLimitCardDays(Constant.LIMIT_CARD_DAYS);
                // 初始化期限卡日期   add [{"date":"20250501", "status": 0}]
                List<LimitCardInfoBo> limitCardInfo = new ArrayList<>();
                LocalDateTime limitCardEndDate = dbPatientCard.getLimitCardStartDate().plusDays(dbPatientCard.getLimitCardDays());
                for (LocalDateTime dateTime = dbPatientCard.getLimitCardStartDate(); dateTime.compareTo(limitCardEndDate) <= 0 ; dateTime=dateTime.plusDays(1)) {
                    String date = DateUtil.dateToString(dateTime, DateUtil.YMN);
                    LimitCardInfoBo limitCardInfoBo = new LimitCardInfoBo();
                    limitCardInfoBo.setDate(date);
                    limitCardInfoBo.setStatus(0);
                    limitCardInfo.add(limitCardInfoBo);
                }
                dbPatientCard.setLimitCardInfo(JSONArray.toJSONString(limitCardInfo));
            }
            patientCardService.save(dbPatientCard);
        }
        return ApiResult.success(userCardList);
    }

    private void checkLimitCard(PatientCardAddReqDTO userCardAddReqDto) {
        // 入参是否有期限卡
        long limitCardCount = userCardAddReqDto.getUserCardList().stream().filter(cardDto -> cardDto.getCardType().equals(CardTypeEnum.LIMIT_DATE_CARD.getCode())).count();
        // 有则校验是否已经购买过期限卡
        if (limitCardCount > 0) {
            List<PatientCard> limitCardList = patientCardService.list(new LambdaQueryWrapper<PatientCard>().eq(PatientCard::getPatientId, userCardAddReqDto.getPatientId()).eq(PatientCard::getCardType, CardTypeEnum.LIMIT_DATE_CARD.getCode()));
            if (!CollectionUtils.isEmpty(limitCardList)) {
                log.error("已购买过期限卡，无法再次购买");
                throw new BusinessException(ResponseCodeEnum.EXIST_LIMIT_CARD.getMsg());
            }
        }
    }
}
